package com.mall.user.services;

import com.alibaba.fastjson.JSON;
import com.mall.commons.mq.producer.RocketMqProducer;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.IUserRegisterService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.entitys.UserVerify;
import com.mall.user.dal.persistence.MemberMapper;
import com.mall.user.dal.persistence.UserVerifyMapper;
import com.mall.user.dto.UserRegisterRequest;
import com.mall.user.dto.UserRegisterResponse;
import com.mall.user.dto.UserVerifyRequest;
import com.mall.user.dto.UserVerifyResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@Slf4j
@Component
public class RegisterServiceImpl implements IUserRegisterService {


    @Autowired
    MemberMapper memberMapper;
    @Autowired
    UserVerifyMapper verifyMapper;

    @Autowired
    JavaMailSender mailSender;

    @Autowired
    RocketMqProducer rocketMqProducer;

    //TODO:占位符
    @Value("${email.text}")
    private String emailStr;

    private ExecutorService executorService;

    @Autowired
    public void init() {
        executorService = Executors.newSingleThreadExecutor();
    }

    @Override
    public UserRegisterResponse register(UserRegisterRequest request) {
        // 参数校验
        request.requestCheck();

        // 验证用户名是否重复
        log.info("start check duplicate name in register!");
        validDuplicatedName(request);

        // 1. 用户名唯一则插入用户表中
        int effectiveRows = insertMember(request);
        UserRegisterResponse registerResponse = new UserRegisterResponse();

        if (effectiveRows != 1) {
            // 插入失败
            registerResponse.setCode(SysRetCodeConstants.USER_REGISTER_FAILED.getCode());
            registerResponse.setMsg(SysRetCodeConstants.USER_REGISTER_FAILED.getMessage());
            return registerResponse;
        }


        // 2. 向用户验证表中插入一条记录
        UserVerify userVerify = new UserVerify();
        effectiveRows = insertUserVerify(userVerify, request);
        if (effectiveRows != 1) {
            // 插入失败
            registerResponse.setCode(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getCode());
            registerResponse.setMsg(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getMessage());
            return registerResponse;
        }

        // 3. 发送用户激活邮件
        // TODO 发送用户激活邮件

        Map<String, String> map = new HashMap<>();
        map.put("username", userVerify.getUsername());
        map.put("key", userVerify.getUuid());
        map.put("email", request.getEmail());
        sendEmail(map);


        // 打印日志：
        log.info("注册成功，注册参数:{},{}", JSON.toJSONString(request), "xxx");
        registerResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        registerResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return registerResponse;
    }

    @Override
    public UserVerifyResponse verify(UserVerifyRequest request) {
        // 检验请求参数
        request.requestCheck();

        // 先根据uuid查找，验证表中，相应的用户
        Example example = new Example(UserVerify.class);
        example.createCriteria().andEqualTo("uuid", request.getUuid());
        List<UserVerify> userVerifies = verifyMapper.selectByExample(example);
        UserVerify verify = userVerifies.get(0);
        UserVerifyResponse userVerifyResponse = new UserVerifyResponse();

        if (CollectionUtils.isEmpty(userVerifies) ||
                !verify.getUsername().equals(request.getUserName())) {
            userVerifyResponse.setCode(SysRetCodeConstants.USERVERIFY_INFOR_INVALID.getCode());
            userVerifyResponse.setMsg(SysRetCodeConstants.USERVERIFY_INFOR_INVALID.getMessage());
            return userVerifyResponse;
        }

        // 修改验证表
        verify.setIsVerify("Y");
        int effectiveCount = verifyMapper.updateByExample(verify, example);
        if (effectiveCount != 1) {
            userVerifyResponse.setCode(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getCode());
            userVerifyResponse.setMsg(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getMessage());
            return userVerifyResponse;
        }

        // 修改用户表
        Example memberExample = new Example(Member.class);
        memberExample.createCriteria().andEqualTo("username", verify.getUsername());

        List<Member> members = memberMapper.selectByExample(memberExample);
        Member member = members.get(0);
        member.setUpdated(new Date());
        member.setIsVerified("Y");

        effectiveCount = memberMapper.updateByExample(member, memberExample);
        if (effectiveCount != 1) {
            userVerifyResponse.setCode(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getCode());
            userVerifyResponse.setMsg(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getMessage());
            return userVerifyResponse;
        }

        userVerifyResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        userVerifyResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return userVerifyResponse;
    }


    /**
     *
     */
    private void sendEmail(Map<String, String> emmailMap) {


        try {
            String mail = emmailMap.get("email");
            String username = emmailMap.get("username");
            String uid = emmailMap.get("key");

            SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
            simpleMailMessage.setTo(mail);
            simpleMailMessage.setFrom("869651544@qq.com");
            simpleMailMessage.setSubject("CSMALL 商城激活");
            String text = String.format(emailStr, username, uid);
            simpleMailMessage.setText(text);

            try {
                executorService.submit(() -> mailSender.send(simpleMailMessage));
            } catch (MailException e) {

            }
            log.info("邮件发送成功，邮件内容：{}，收件人地址：{}", text, mail);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private int insertUserVerify(UserVerify userVerify, UserRegisterRequest request) {
        userVerify.setUsername(request.getUserName());
        String uniqueKey = request.getUserName() + request.getUserPwd() + UUID.randomUUID();
        String uuid = DigestUtils.md5DigestAsHex(uniqueKey.getBytes());
        userVerify.setUuid(uuid);
        userVerify.setIsVerify("N");
        userVerify.setIsExpire("N");
        userVerify.setRegisterDate(new Date());
        return verifyMapper.insert(userVerify);
    }

    /*
         向用户表中插入一条记录
     */
    private int insertMember(UserRegisterRequest request) {
        Member member = new Member();
        member.setUsername(request.getUserName());
        member.setEmail(request.getEmail());
        // 存储加密的Password
        String pwd = DigestUtils.md5DigestAsHex(request.getUserPwd().getBytes());

        member.setCreated(new Date());
        member.setUpdated(new Date());
        member.setPassword(pwd);
        member.setIsVerified("N");
        member.setState(1);

        return memberMapper.insert(member);
    }

    /*
         验证用户名是否重复(向用户表插入一条记录)
     */
    private void validDuplicatedName(UserRegisterRequest request) {

        Example example = new Example(Member.class);

        example.createCriteria().andEqualTo("username", request.getUserName());
        List<Member> members = memberMapper.selectByExample(example);
        log.info("check registered userinfo: " + members);

        if (!CollectionUtils.isEmpty(members)) {
            throw new ValidateException(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getCode(),
                    SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getMessage());
        }
    }
}
